//================================================//
// Created by dracana				  //
// Desc: Crafted Wine Keg item and definitions.   //
//================================================//
using System;
using System.Collections;
using Server;
using Server.Network;
using Server.Engines.Craft;

using Server.Multis;
using Server.Gumps;
using Server.ContextMenus;
//using Server.Mobiles;
//using Server.Accounting;
//using Server.Items;
//using Server.Misc;
//using Server.Targeting;
using System.Collections.Generic;//list

namespace Server.Items
{
	public class WineKeg : Item, ICraftable, ISecurable
	{
		public static readonly TimeSpan CheckDelay = TimeSpan.FromDays( 7.0 );

		private int m_Held;
		private Mobile m_Crafter;
		private WineQuality m_Quality;
		private GrapeVariety m_Variety;
		private DateTime m_Start;
		private double m_BottleDuration;
		private bool m_AllowBottling;
		
		private SecureLevel m_Level;
		[CommandProperty(AccessLevel.GameMaster)]
		public SecureLevel Level{get { return m_Level; }set { m_Level = value; }}
		
		
		[CommandProperty( AccessLevel.GameMaster )]
		public int Held
		{
			get
			{
				return m_Held;
			}
			set
			{
				if ( m_Held != value )
				{
					this.Weight += (value - m_Held) * 0.8;

					m_Held = value;
					InvalidateProperties();
				}
			}
		}
		
		[CommandProperty( AccessLevel.GameMaster )]
		public GrapeVariety Variety
		{
			get
			{
				return m_Variety;
			}
			set
			{
				if ( m_Variety != value )
				{
					m_Variety = value;

					InvalidateProperties();
				}
			}
		}
		
		[CommandProperty( AccessLevel.GameMaster )]
		public Mobile Crafter
		{
			get{ return m_Crafter; }
			set{ m_Crafter = value; InvalidateProperties(); }
		}

		
		[CommandProperty( AccessLevel.GameMaster )]
		public WineQuality Quality
		{
			get{ return m_Quality; }
			set{ m_Quality = value; InvalidateProperties(); }
		}
		
		[CommandProperty( AccessLevel.GameMaster )]
		public bool AllowBottling
		{
			get
			{
				if ( !m_AllowBottling )
					m_AllowBottling = ( 0 >= TimeSpan.Compare( TimeSpan.FromDays( m_BottleDuration ),
						DateTime.Now.Subtract( m_Start )));				
				return m_AllowBottling;
			}
			set { m_AllowBottling = value; }
		}

		[CommandProperty( AccessLevel.GameMaster )]
		public double BottleDuration
		{
			get { return m_BottleDuration; }
			set { m_BottleDuration = value; }
		}

		public WineKeg( Serial serial ) : base( serial )
		{
		}

		private static void SetSaveFlag( ref SaveFlag flags, SaveFlag toSet, bool setIf )
		{
			if ( setIf )
				flags |= toSet;
		}

		private static bool GetSaveFlag( SaveFlag flags, SaveFlag toGet )
		{
			return ( (flags & toGet) != 0 );
		}

		[Flags]
		private enum SaveFlag
		{
			None				= 0x00000000,
			Held				= 0x00000001,
			Crafter				= 0x00000002,
			Quality				= 0x00000004,
			Variety				= 0x00000008
		}
		
		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );
			
			writer.Write( (int) 2 ); // version
			//version 2
            writer.Write((int)m_Level);
			writer.Write( (DateTime)m_Start );
			writer.Write( (double)m_BottleDuration );
			writer.Write( (bool)m_AllowBottling );
				
			//version 1
			SaveFlag flags = SaveFlag.None;
			
			SetSaveFlag( ref flags, SaveFlag.Held, m_Held != 0 );
			SetSaveFlag( ref flags, SaveFlag.Crafter, m_Crafter != null );
			SetSaveFlag( ref flags, SaveFlag.Quality, m_Quality != WineQuality.Regular );
			SetSaveFlag( ref flags, SaveFlag.Variety, m_Variety != DefaultVariety );

			writer.WriteEncodedInt( (int) flags );

			if ( GetSaveFlag( flags, SaveFlag.Held ) )
				writer.Write( (int) m_Held );
			if ( GetSaveFlag( flags, SaveFlag.Crafter ) )
				writer.Write( (Mobile) m_Crafter );
			if ( GetSaveFlag( flags, SaveFlag.Quality ) )
				writer.WriteEncodedInt( (int) m_Quality );
			if ( GetSaveFlag( flags, SaveFlag.Variety ) )
				writer.WriteEncodedInt( (int) m_Variety );
		}
		
		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );
			
			int version = reader.ReadInt();

			switch ( version )
			{
				case 2:
				{
					m_Level = (SecureLevel)reader.ReadInt();
					m_Start = reader.ReadDateTime();
					m_BottleDuration = reader.ReadDouble();
					m_AllowBottling = reader.ReadBool();
					
					goto case 1;
				}
				case 1:	
				{
					SaveFlag flags = (SaveFlag)reader.ReadEncodedInt();

					if ( GetSaveFlag( flags, SaveFlag.Held ) )
						m_Held = reader.ReadInt();
		
					if ( GetSaveFlag( flags, SaveFlag.Crafter ) )
						m_Crafter = reader.ReadMobile();

					if ( GetSaveFlag( flags, SaveFlag.Quality ) )
						m_Quality = (WineQuality)reader.ReadEncodedInt();
					else
						m_Quality = WineQuality.Regular;
	
					if ( m_Quality == WineQuality.Low )
						m_Quality = WineQuality.Regular;

					if ( GetSaveFlag( flags, SaveFlag.Variety ) )
						m_Variety = (GrapeVariety)reader.ReadEncodedInt();
					else
						m_Variety = DefaultVariety;
	
					if ( m_Variety == GrapeVariety.None )
						m_Variety = DefaultVariety;
						
					break;
				}
			}
		}
		
		public virtual GrapeVariety DefaultVariety{ get{ return GrapeVariety.CabernetSauvignon; } }


		[Constructable]
		public WineKeg( ) : base( 0x1940 )
		{
			this.Weight = 1.0;
			
			m_Held = 75;
			m_Quality = WineQuality.Regular;
			m_Crafter = null;
			m_Variety = DefaultVariety;
			m_BottleDuration = 7.0;
			m_AllowBottling = false;
			m_Start = DateTime.Now;
		}

		public override void AddNameProperty( ObjectPropertyList list )
		{
			if (this.Name == null )
			{
				if ( m_Crafter != null )
					list.Add( m_Crafter.Name+" Vineyards" );
				else
					list.Add( "Cheap Table Wine" );
			}
			else
			{
				list.Add (this.Name);
			}
		}
		
		public override void AddNameProperties( ObjectPropertyList list )
 		{
 			base.AddNameProperties( list );
 			
			string wineType;
			wineType = WinemakingResources.GetName( m_Variety );
 			
			if ( m_Quality == WineQuality.Exceptional )
			{
 				list.Add( 1060847, "Special Reserve\t{0}", wineType );
 			}
 			else
 			{
 				list.Add( 1060847, "\t{0}", wineType );
 			}
 		}
		
		public override void GetProperties( ObjectPropertyList list )
		{
			base.GetProperties( list );

			int number;

			if ( m_Held <= 0 )
				number = 502246; // The keg is empty.
			else if ( m_Held < 5 )
				number = 502248; // The keg is nearly empty.
			else if ( m_Held < 10 )
				number = 502249; // The keg is not very full.
			else if ( m_Held < 18 )
				number = 502250; // The keg is about one quarter full.
			else if ( m_Held < 25 )
				number = 502251; // The keg is about one third full.
			else if ( m_Held < 32 )
				number = 502252; // The keg is almost half full.
			else if ( m_Held < 38 )
				number = 502254; // The keg is approximately half full.
			else if ( m_Held < 45 )
				number = 502253; // The keg is more than half full.
			else if ( m_Held < 56 )
				number = 502255; // The keg is about three quarters full.
			else if ( m_Held < 64 )
				number = 502256; // The keg is very full.
			else if ( m_Held < 75 )
				number = 502257; // The liquid is almost to the top of the keg.
			else
				number = 502258; // The keg is completely full.

			list.Add( number );
		}

		public override void OnSingleClick( Mobile from )
		{
			base.OnSingleClick( from );

			int number;
			string wineType;
			
			if (this.Name == null )
			{
				if ( m_Crafter != null )
					this.LabelTo( from, "{0} Vinyards", m_Crafter.Name );
				else
					this.LabelTo( from, "Cheap Table Wine" );
			}
			else
			{
				this.LabelTo( from, "{0}", this.Name );
			}
			
			wineType = WinemakingResources.GetName( m_Variety );
 			
			if ( m_Quality == WineQuality.Exceptional )
			{
				this.LabelTo( from, "Special Reserve {0}", wineType );
 			}
 			else
 			{
 				this.LabelTo( from, "{0}", wineType );
 			}

			if ( m_Held <= 0 )
				number = 502246; // The keg is empty.
			else if ( m_Held < 5 )
				number = 502248; // The keg is nearly empty.
			else if ( m_Held < 10 )
				number = 502249; // The keg is not very full.
			else if ( m_Held < 18 )
				number = 502250; // The keg is about one quarter full.
			else if ( m_Held < 25 )
				number = 502251; // The keg is about one third full.
			else if ( m_Held < 32 )
				number = 502252; // The keg is almost half full.
			else if ( m_Held < 38 )
				number = 502254; // The keg is approximately half full.
			else if ( m_Held < 45 )
				number = 502253; // The keg is more than half full.
			else if ( m_Held < 56 )
				number = 502255; // The keg is about three quarters full.
			else if ( m_Held < 64 )
				number = 502256; // The keg is very full.
			else if ( m_Held < 75 )
				number = 502257; // The liquid is almost to the top of the keg.
			else
				number = 502258; // The keg is completely full.

			this.LabelTo( from, number );
		}

		public override void OnDoubleClick( Mobile from )
		{
			if ( AllowBottling )
			{
				if ( from.InRange( GetWorldLocation(), 2 ) )
				{
					if ( m_Held > 0 )
					{
						Container pack = from.Backpack;

						if ( pack != null && pack.ConsumeTotal( typeof( EmptyWineBottle ), 1 ) )
						{
							from.SendLocalizedMessage( 502242 ); // You pour some of the keg's contents into an empty bottle...

							BaseCraftWine wine = FillBottle();
							wine.Crafter = m_Crafter;
							wine.Quality = m_Quality;
							wine.Variety = m_Variety;
							if (this.Name != null)
								wine.Name = this.Name;
	
							if ( pack.TryDropItem( from, wine, false ) )
							{
								from.SendLocalizedMessage( 502243 ); // ...and place it into your backpack.
								from.PlaySound( 0x240 );

								if ( --Held == 0 )
								{
									this.Delete();
	
									if ( GiveKeg( from ) )
									{
										from.SendMessage( "The Keg is empty and you clean it for reuse" ); 
									}
									else
									{
										from.SendMessage( "The Keg is now empty and cannot be reused." );
									}
								}
							}
							else
							{
								from.SendLocalizedMessage( 502244 ); // ...but there is no room for the bottle in your backpack.
								wine.Delete();
							}
						}
					}
					else
					{
						from.SendLocalizedMessage( 502246 ); // The keg is empty.
					}
				}
				else
				{
					from.LocalOverheadMessage( Network.MessageType.Regular, 0x3B2, 1019045 ); // I can't reach that.
				}
			}
			else
			{
				from.SendMessage( "This keg is not ready to bottle yet, the fermentation process is not yet complete." );
			}
		}
		
#region CheckAccess


			public bool CheckAccess(Mobile m)
        	{
        	BaseHouse house = BaseHouse.FindHouseAt(this);

			if (house == null)
				return false;

			if (!house.IsAosRules)
				return true;

			if (house.Public ? house.IsBanned(m) : !house.HasAccess(m))
				return false;

			return house.HasSecureAccess(m, m_Level);
			}
        

#endregion CheckAccess


#region Item Context Menu
        public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
        	{
//        	from.PlaySound(0x482);
//        	from.Say("There is something strange.");
//        	Effects.SendLocationEffect( this,Map, 0x3709, 13, 0x3B2, 0 );
//        	Effects.SendLocationEffect( from,Map, 0x3709, 13, 0x3B2, 0 );
//
         	SecureLevel securelevel = this.m_Level;
        	BaseHouse house = BaseHouse.FindHouseAt(this);
        	if (house != null && house.IsOwner(from))
        		{
        		SetSecureLevelEntry.AddTo(from, this, list);
        		}
//        	if (!CheckAccess(from))
//        		{
//        		if (house == null)
//        			{
//        			base.GetContextMenuEntries(from, list);
//        			list.Add(new MenuEntry(from, this));
//        			}
//        		else
//        			{
//        			from.SendLocalizedMessage( 1061637 ); // You are not allowed to access this.
//        			}
//        		}
//        	else
//        		{
//        			base.GetContextMenuEntries(from, list);
//        			list.Add(new MenuEntry(from, this));
//        		}
        	}


//        private class MenuEntry : ContextMenuEntry
//        	{
//        	private WineKeg m_Item;
//			private Mobile m_Mobile;
//
//			public MenuEntry(Mobile from, Item item)
//				: base(159) // uses 3000159
//			{
//				m_Item = item as WineKeg;
//				m_Mobile = from;
//			}
//
//			public override void OnClick()
//			{
//				// send gump
////				m_Mobile.CloseGump(typeof(DragonKnightsGhostClockGump));
////				m_Mobile.SendGump(new DragonKnightsGhostClockGump(m_Item.Name));
////				m_Mobile.PlaySound(0x507);
////				m_Mobile.Say ("Who you gona call?");
//			}
//		}


#endregion Item Context Menu Stuf

		public bool GiveKeg( Mobile m )
		{
			Container pack = m.Backpack;

			Keg keg = new Keg();

			if ( pack == null || !pack.TryDropItem( m, keg, false ) )
			{
				keg.Delete();
				return false;
			}

			return true;
		}

		public BaseCraftWine FillBottle()
		{
			switch ( m_Variety )
			{
				default: return new BottleOfWine();
			}
		}

		public static void Initialize()
		{
			TileData.ItemTable[0x1940].Height = 4;
		}
		
		#region ICraftable Members
		public int OnCraft( int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, CraftItem craftItem, int resHue )
		{
			Held = 75;
			
			Quality = (WineQuality)quality;

			if ( makersMark )
				Crafter = from;
				
			Item[] items = from.Backpack.FindItemsByType( typeof( VinyardLabelMaker ) );

			if ( items.Length != 0 )
			{
				foreach( VinyardLabelMaker lm in items )
				{
					if (lm.VinyardName != null)
					{
						this.Name = lm.VinyardName;
						break;
					}
				}
			}

			Type resourceType = typeRes;

			if ( resourceType == null )
				resourceType = craftItem.Resources.GetAt( 0 ).ItemType;

			Variety = WinemakingResources.GetFromType( resourceType );

			CraftContext context = craftSystem.GetContext( from );

			Hue = 0;
			
			BottleDuration = 7.0;
			AllowBottling = false;
			m_Start = DateTime.Now;

			return quality;
		}
		#endregion
	}
}
